#include "ColorPatchFeatExtractor.h"
#include <math.h>
#include <iostream>
using namespace std;
/********************************************************************/
CColorPatchFeatExtractor::CColorPatchFeatExtractor(void)
{
	m_GridSz = 3; 
}
/********************************************************************/
CColorPatchFeatExtractor::~CColorPatchFeatExtractor(void)
{
}
/********************************************************************/
TFeatureVector CColorPatchFeatExtractor::ExtractFeaturesFromImage( IplImage * img )
{
	TFeatureVector retVal;
	if( NULL == img )
	{
		return retVal; 
	}
		//
	int w = img->width;
	int h = img->height;
	int ws = w/m_GridSz;
	int hs = h/m_GridSz; 
	// copy image to HSV space.
	IplImage* hsvImg = cvCreateImage(cvSize(w,h),img->depth, img->nChannels );
	IplImage* hImg = cvCreateImage(cvSize(w,h), img->depth, 1);
	IplImage* sImg = cvCreateImage(cvSize(w,h), img->depth, 1);
	IplImage* vImg = cvCreateImage(cvSize(w,h), img->depth, 1);
	cvCvtColor(img,hsvImg, CV_RGB2HSV );
	cvSetImageCOI(hsvImg, 1);
	cvCopy(hsvImg,hImg);
	cvSetImageCOI(hsvImg, 2);
	cvCopy(hsvImg,sImg);
	cvSetImageCOI(hsvImg, 3);
	cvCopy(hsvImg,vImg);
	int x0=0,x1=0, y0=0, y1=0;
	double v=0.00,m=0.00,s=0.00;
	for( int i=0; i < m_GridSz; ++i )
	{
		x0 = i*ws;
		x1 = (i+1)*ws;
		for( int j=0; j < m_GridSz; ++j )
		{
			y0 = j*hs;
			y1 = (j+1)*hs;
			cvSetImageROI(hImg, cvRect(x0,y0,ws,hs));
			cvSetImageROI(sImg, cvRect(x0,y0,ws,hs));
			cvSetImageROI(vImg, cvRect(x0,y0,ws,hs));
			CalculateStats( hImg, v,m,s);
			retVal.push_back(v);
			retVal.push_back(m);
			retVal.push_back(s);
			CalculateStats( sImg, v,m,s);
			retVal.push_back(v);
			retVal.push_back(m);
			retVal.push_back(s);
			CalculateStats( vImg, v,m,s);
			retVal.push_back(v);
			retVal.push_back(m);
			retVal.push_back(s);
			cvResetImageROI(hImg);
			cvResetImageROI(sImg);
			cvResetImageROI(vImg);
		}
	}

	cvReleaseImage(&hsvImg);
	cvReleaseImage(&hImg);
	cvReleaseImage(&sImg);
	cvReleaseImage(&vImg);
	return retVal; 
}
/********************************************************************/
TDataSet CColorPatchFeatExtractor::ExtractFeaturesFromData( CDataPointManager * dpMgr,bool loadImages)
{
	TDataSet retVal;
	if( NULL == dpMgr )
		return retVal;
	int sz = dpMgr->GetSize();
	for( int i = 0; i < sz; i++ )
	{
		if(loadImages)
		{
			dpMgr->GetDataPoint(i)->LoadSourceImage();
		}
		if( dpMgr->GetDataPoint(i)->HasImage() )
		{
			cout << "Loaded image " << i << " name: " << dpMgr->GetDataPoint(i)->GetInFile() << endl; 
			TFeatureVector temp = ExtractFeaturesFromImage( dpMgr->GetDataPoint(i)->GetImage() );
			cout << ">>>Loaded " << temp.size() << " from image " << i << endl; 
			retVal.push_back(temp);
			if( loadImages )
			{
				dpMgr->GetDataPoint(i)->FreeImage();
			}
		}
		else
		{
			cout << "Failed to load image: " << dpMgr->GetDataPoint(i)->GetInFile();
		}
	}
	return retVal;
}
/********************************************************************/
/*TDataSet CColorPatchFeatExtractor::Normalize( TDataSet& data )
{
	TDataSet retVal; 
	// we're just applying the whitening transform
	// f' = f-mu/sigma
	TFeatureVector means;
	TFeatureVector stdDev;
	CalculateAverages( data, means, stdDev );
	int nfeatures = static_cast<int>(data[0].size());
	int nDataPts = static_cast<int>(data.size());
	// for each image
	double temp =0.00;
	for( int i=0; i<nDataPts; i++ )
	{
		for(int j=0; j<nfeatures; j++ )
		{
			temp = data[i][j];
			data[i][j] = (temp-means[j])/stdDev[j];
		}
	}

	return retVal;
}*/
/********************************************************************/
TFeatureVectorLabel CColorPatchFeatExtractor::GetLabels( void )
{
	TFeatureVectorLabel retVal;
	return retVal; 
}
/********************************************************************/
void CColorPatchFeatExtractor::SetGridDim( int grid )
{
	if( grid > 0 )
		m_GridSz = grid;
}
/********************************************************************/
int CColorPatchFeatExtractor::GetGridDim( void )
{
	return m_GridSz; 
}
/********************************************************************/
void CColorPatchFeatExtractor::CalculateStats( IplImage* img, double& variance, double& mean, double& skew)
{
	int w = img->roi->width;
	int h = img->roi->height; 
	IplImage * sqrd = cvCreateImage(cvSize(w,h), img->depth,img->nChannels);
	IplImage * mean_img = cvCreateImage(cvSize(w,h), img->depth,img->nChannels);
	IplImage * temp = cvCreateImage(cvSize(w,h), img->depth,img->nChannels);
	CvScalar m, s;
	cvAvgSdv(img,&m,&s);
	cvZero(mean_img);
	// create an image of the mean value
	cvScale(mean_img,mean_img,1.0,m.val[0]);
	cvCopy(img,temp);
	// subtract of the mean
	cvSub(temp,mean_img,temp);
	// cube the values
	cvMul(temp,temp,sqrd);
	cvMul(temp,sqrd,temp);
	double scale = 1/sqrt( s.val[0]*s.val[0]*s.val[0] ); 
	CvScalar numerator = cvAvg(temp);
	// calculate the average  and skew
	skew = numerator.val[0]/scale; 
	mean = m.val[0];
	variance = s.val[0];

	cvReleaseImage( &temp ); 
	cvReleaseImage( &sqrd ); 
	cvReleaseImage( &mean_img ); 
}
/********************************************************************/
/*TFeatureVector  CColorPatchFeatExtractor::GetAllFeatures( TDataSet data, int feature )
{
	TFeatureVector retVal;
	TDataSetIter images;
	for( images = data.begin(); images != data.end(); ++images )
	{
		retVal.push_back(images->at(feature));
	}
	return retVal;
}*/
/********************************************************************/
/*void CColorPatchFeatExtractor::CalculateAverages( TDataSet data, TFeatureVector& means, TFeatureVector& stdDev )
{
	int nfeatures = static_cast<int>(data[0].size());
	double nDataPts = static_cast<double>(data.size());
	for( int i=0; i<nfeatures; ++i )
	{
		TFeatureVector temp = GetAllFeatures( data, i );
		TFeatureVectorIter iter; 
		double accumulator = 0.00;
		for( iter = temp.begin(); iter != temp.end(); ++iter )
		{
			accumulator += *iter;
		}
		double mu = accumulator/nDataPts;
		accumulator = 0.00;
		for( iter = temp.begin(); iter != temp.end(); ++iter )
		{
			accumulator += (*iter-mu)*(*iter-mu);
		}
		double var = accumulator/nDataPts;
		means.push_back(mu);
		stdDev.push_back(sqrt(var)); 
	}
}*/
/********************************************************************/